using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace MouseKeyboardOperationSimulator
{
    /// <summary>
    /// 键盘钩子管理类
    /// </summary>
    public class KeyboardHookManager
    {
        // Win32 API声明用于按键钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr GetModuleHandle(string lpModuleName);
        


        // 定义委托和常量
        const int WH_KEYBOARD_LL = 13;
        const int WM_KEYDOWN = 0x0100;
        const int WM_KEYUP = 0x0101;
        const int WM_SYSKEYDOWN = 0x0104;
        const int WM_SYSKEYUP = 0x0105;

        // 定义按键结构体
        [StructLayout(LayoutKind.Sequential)]
        struct KBDLLHOOKSTRUCT
        {
            public uint vkCode;
            public uint scanCode;
            public uint flags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        // 定义委托
        delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        // 键盘钩子相关变量
        private LowLevelKeyboardProc _proc;
        private IntPtr _hookID = IntPtr.Zero;
        private List<string> _pressedKeys = new List<string>();
        
        // 回调事件
        public event EventHandler<KeyEventArgs> KeyPressed;

        /// <summary>
        /// 构造函数
        /// </summary>
        public KeyboardHookManager()
        {
            _proc = new LowLevelKeyboardProc(HookCallback);
            _pressedKeys = new List<string>();
        }

        /// <summary>
        /// 安装键盘钩子
        /// </summary>
        public void StartHook()
        {
            _hookID = SetHook(_proc);
        }

        /// <summary>
        /// 卸载键盘钩子
        /// </summary>
        public void StopHook()
        {
            UnhookWindowsHookEx(_hookID);
        }

        /// <summary>
        /// 设置钩子
        /// </summary>
        private IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                    GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        /// <summary>
        /// 键盘钩子回调函数
        /// </summary>
        private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                // 检查是否是按键按下事件
                if (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
                {
                    // 获取按键信息
                    KBDLLHOOKSTRUCT kbd = Marshal.PtrToStructure<KBDLLHOOKSTRUCT>(lParam);
                    
                    // 获取按键名称
                    string keyName = GetKeyName(kbd.vkCode);
                    
                    // 添加到已按下按键列表
                    if (!_pressedKeys.Contains(keyName))
                    {
                        _pressedKeys.Add(keyName);
                    }
                    
                    // 触发按键事件
                    KeyPressed?.Invoke(this, new KeyEventArgs(keyName, new List<string>(_pressedKeys)));
                }
                // 检查是否是按键释放事件
                else if (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)
                {
                    // 获取按键信息
                    KBDLLHOOKSTRUCT kbd = Marshal.PtrToStructure<KBDLLHOOKSTRUCT>(lParam);
                    
                    // 获取按键名称
                    string keyName = GetKeyName(kbd.vkCode);
                    
                    // 从已按下按键列表中移除
                    if (_pressedKeys.Contains(keyName))
                    {
                        _pressedKeys.Remove(keyName);
                    }
                }
            }
            
            // 传递给下一个钩子
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        /// <summary>
        /// 获取按键名称
        /// </summary>
        private string GetKeyName(uint virtualKeyCode)
        {
            Keys key = (Keys)virtualKeyCode;
            switch (key)
            {
                case Keys.ControlKey:
                    return "Ctrl";
                case Keys.LControlKey:
                    return "Ctrl";
                case Keys.RControlKey:
                    return "Ctrl";
                case Keys.Menu:
                    return "Alt";
                case Keys.LMenu:
                    return "Alt";
                case Keys.RMenu:
                    return "Alt";
                case Keys.ShiftKey:
                    return "Shift";
                case Keys.LShiftKey:
                    return "Shift";
                case Keys.RShiftKey:
                    return "Shift";
                case Keys.Return:
                    return "Enter";
                case Keys.Space:
                    return "Space";
                default:
                    return key.ToString();
            }
        }
    }

    /// <summary>
    /// 按键事件参数
    /// </summary>
    public class KeyEventArgs : EventArgs
    {
        public string KeyName { get; }
        public List<string> PressedKeys { get; }

        public KeyEventArgs(string keyName, List<string> pressedKeys)
        {
            KeyName = keyName;
            PressedKeys = pressedKeys;
        }
    }


}